package com.clei.utils;

import com.clei.dto.ObsObjDTO;
import com.obs.services.ObsClient;
import com.obs.services.exception.ObsException;
import com.obs.services.model.ObjectMetadata;
import com.obs.services.model.ObsObject;
import com.obs.services.model.TemporarySignatureResponse;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

/**
 * 华为 OBS util
 *
 * @author Y
 * @date 2023-09-15
 **/
public class ObsUtil {

    /**
     * bucket
     */
    private final static String BUCKET = "";

    /**
     * endpoint
     */
    private final static String END_POINT = "";

    /**
     * accessKey
     */
    private final static String ACCESS_KEY = "";

    /**
     * accessSecret
     */
    private final static String ACCESS_SECRET = "";

    /**
     * 默认过期时间 两分钟
     */
    private final static long EXPIRE_SECONDS = 120;

    /**
     * dot
     */
    private final static char DOT = '.';

    /**
     * slash
     */
    private final static char SLASH = '/';

    public static void main(String[] args) throws FileNotFoundException {
        /*ObsObjDTO put = put(new File("E:\\CLTemp\\hello.png"));
        PrintUtil.log(put);*/

        /*ObsObjDTO delete = delete("202309/daa0f0d568d44579a85275b20a84a153.png");
        PrintUtil.log(delete);*/

        ObsObjDTO visitUrl = getVisitUrl("202309/daa0f0d568d44579a85275b20a84a153.png");
        PrintUtil.log(visitUrl);

        // ObsObjDTO put = putAndGetVisit(new File("E:\\CLTemp\\darkness.png"));
        // PrintUtil.log(put);

        /*List<File> fileList = new ArrayList<>(3);
        fileList.add(new File("E:\\CLTemp\\hello.png"));
        fileList.add(new File("E:\\CLTemp\\darkness.png"));
        fileList.add(new File("E:\\CLTemp\\my.png"));
        List<ObsObjDTO> obsObjInfos = multiPutAndGetVisit(fileList);
        obsObjInfos.forEach(PrintUtil::log);*/

        // ObsObjDTO delete = delete("202309/ee4cad5a0ae54c2e9597a715c99fa304.png");
        // PrintUtil.log(delete);
    }

    /**
     * put
     *
     * @param file file
     * @return ObsObjDTO
     */
    private static ObsObjDTO put(File file) {
        try (ObsClient obsClient = getObsClient();
             FileInputStream fis = new FileInputStream(file)) {
            String objectKey = getObjectKey(file.getName());
            obsClient.putObject(BUCKET, objectKey, fis);
            return ObsObjDTO.success(objectKey, null);
        } catch (Exception e) {
            PrintUtil.log("put error ", e);
            return ObsObjDTO.fail();
        }
    }

    /**
     * put
     *
     * @param file file
     * @return ObsObjDTO
     */
    private static ObsObjDTO putAndGetVisit(File file) {
        try (ObsClient obsClient = getObsClient();
             FileInputStream fis = new FileInputStream(file)) {
            String objectKey = getObjectKey(file.getName());
            obsClient.putObject(BUCKET, objectKey, fis);
            TemporarySignatureResponse tempSignRes = obsClient.createGetTemporarySignature(BUCKET, objectKey, null, EXPIRE_SECONDS, null, null);
            return ObsObjDTO.success(objectKey, tempSignRes.getSignedUrl());
        } catch (Exception e) {
            PrintUtil.log("putAndGetVisit error ", e);
            return ObsObjDTO.fail();
        }
    }

    /**
     * multiPut
     * 暂不考虑多线程
     *
     * @param fileList fileList
     * @return ObsObjDTO list
     */
    private static List<ObsObjDTO> multiPut(List<File> fileList) {
        List<ObsObjDTO> resList = new ArrayList<>(fileList.size());
        try (ObsClient obsClient = getObsClient()) {
            for (File file : fileList) {
                try (FileInputStream fis = new FileInputStream(file)) {
                    String objectKey = getObjectKey(file.getName());
                    obsClient.putObject(BUCKET, objectKey, fis);
                    resList.add(ObsObjDTO.success(objectKey, null));
                } catch (Exception e) {
                    PrintUtil.log("multiPut error ", e);
                    resList.add(ObsObjDTO.fail());
                }
            }
        } catch (Exception e) {
            // 不会执行到这里
        }
        return resList;
    }

    /**
     * multiPutAndGetVisit
     * 暂不考虑多线程
     *
     * @param fileList fileList
     * @return ObsObjDTO list
     */
    private static List<ObsObjDTO> multiPutAndGetVisit(List<File> fileList) {
        List<ObsObjDTO> resList = new ArrayList<>(fileList.size());
        try (ObsClient obsClient = getObsClient()) {
            for (File file : fileList) {
                try (FileInputStream fis = new FileInputStream(file)) {
                    String objectKey = getObjectKey(file.getName());
                    obsClient.putObject(BUCKET, objectKey, fis);
                    TemporarySignatureResponse tempSignRes = obsClient.createGetTemporarySignature(BUCKET, objectKey, null, EXPIRE_SECONDS, null, null);
                    resList.add(ObsObjDTO.success(objectKey, tempSignRes.getSignedUrl()));
                } catch (Exception e) {
                    PrintUtil.log("multiPut error ", e);
                    resList.add(ObsObjDTO.fail());
                }
            }
        } catch (Exception e) {
            // 不会执行到这里
        }
        return resList;
    }

    /**
     * delete
     *
     * @param objectKey objectKey
     */
    private static ObsObjDTO delete(String objectKey) {
        try (ObsClient obsClient = getObsClient()) {
            obsClient.deleteObject(BUCKET, objectKey);
            return ObsObjDTO.success(objectKey, null);
        } catch (Exception e) {
            PrintUtil.log("delete error ", e);
            return ObsObjDTO.fail(objectKey);
        }
    }

    /**
     * get
     *
     * @param objectKey objectKey
     * @return InputStream
     */
    private static InputStream get(String objectKey) {
        try (ObsClient obsClient = getObsClient()) {
            ObsObject object = obsClient.getObject(BUCKET, objectKey);
            return object.getObjectContent();
        } catch (Exception e) {
            PrintUtil.log("get error ", e);
            return null;
        }
    }

    /**
     * getVisitUrl
     * 私有桶 需要获取临时签名url才能访问
     *
     * @param objectKey objectKey
     * @return ObsObjDTO
     */
    private static ObsObjDTO getVisitUrl(String objectKey) {
        try (ObsClient obsClient = getObsClient()) {
            if (!objectExists(obsClient, objectKey)) {
                return ObsObjDTO.fail(objectKey);
            }
            TemporarySignatureResponse tempSignRes = obsClient.createGetTemporarySignature(BUCKET, objectKey, null, EXPIRE_SECONDS, null, null);
            return ObsObjDTO.success(objectKey, tempSignRes.getSignedUrl());
        } catch (Exception e) {
            PrintUtil.log("getVisitUrl error ", e);
            return ObsObjDTO.fail(objectKey);
        }
    }

    /**
     * multiPutAndGetVisit
     * 暂不考虑多线程
     *
     * @param objectKeyList objectKeyList
     * @return ObsObjDTO list
     */
    private static List<ObsObjDTO> MultiGetVisitUrl(List<String> objectKeyList) {
        List<ObsObjDTO> resList = new ArrayList<>(objectKeyList.size());
        try (ObsClient obsClient = getObsClient()) {
            for (String objectKey : objectKeyList) {
                try {
                    if (!objectExists(obsClient, objectKey)) {
                        resList.add(ObsObjDTO.fail(objectKey));
                        continue;
                    }
                    TemporarySignatureResponse tempSignRes = obsClient.createGetTemporarySignature(BUCKET, objectKey, null, EXPIRE_SECONDS, null, null);
                    resList.add(ObsObjDTO.success(objectKey, tempSignRes.getSignedUrl()));
                } catch (Exception e) {
                    PrintUtil.log("MultiGetVisitUrl error ", e);
                    resList.add(ObsObjDTO.fail(objectKey));
                }
            }
        } catch (Exception e) {
            // 不会执行到这里
        }
        return resList;
    }

    /**
     * obj是否存在
     *
     * @param obsClient ObsClient
     * @param objectKey objectKey
     * @return true是 false否
     */
    private static boolean objectExists(ObsClient obsClient, String objectKey) {
        boolean exists = true;
        try {
            ObjectMetadata objectMetadata = obsClient.getObjectMetadata(BUCKET, objectKey);
            PrintUtil.log(objectMetadata);
        } catch (ObsException e) {
            // 不管ResponseCode是不是404，只要发生ObsException，统一当不存在
            PrintUtil.log("ObsException String : {}, headers : {}", e.toString(), e.getResponseHeaders(), e);
            exists = false;
        }
        return exists;
    }

    /**
     * getObsClient
     *
     * @return ObsClient
     */
    private static ObsClient getObsClient() {
        return new ObsClient(ACCESS_KEY, ACCESS_SECRET, END_POINT);
    }

    /**
     * fileName -> objectKey
     * 例 abc.jpg -> 202309/81e1cce69dde44ff815ab0804a2dcdd8.jpg
     *
     * @param fileName
     * @return objectKey
     */
    private static String getObjectKey(String fileName) {
        String suffix = FileUtil.getSuffix(fileName);
        String objectKey = getTodayNumber() + SLASH + StringUtil.uuid();
        if (suffix.length() > 0) {
            objectKey = objectKey + DOT + suffix;
        }
        return objectKey;
    }

    /**
     * 获取当日 仅数字
     *
     * @return yyyyMMdd
     */
    private static String getTodayNumber() {
        LocalDate now = LocalDate.now();
        return String.valueOf(now.getYear() * 10000 + now.getMonthValue() * 100 + now.getDayOfMonth());
    }
}
